package org.Yiran.timetale_re.block.base;

import net.minecraft.core.particles.BlockParticleOption;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.DirectionalBlock;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.BlockGetter;
import org.Yiran.timetale_re.util.geometry.ModelJsonVoxelShapeParser;
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 自动体素形状方块基类
 * <p>
 * 这个抽象类为需要根据模型文件自动生成碰撞和渲染形状的方块提供了基础实现。
 * 它使用ModelJsonVoxelShapeParser来解析JSON模型文件并生成对应的VoxelShape。
 */
public abstract class AutoVoxelShapeBlock extends DirectionalBlock {
    // 面向属性，定义方块的朝向
    public static final DirectionProperty FACING = DirectionalBlock.FACING;
    
    // 形状生成器，用于根据模型文件生成VoxelShape
    protected final ModelJsonVoxelShapeParser.CachedShapeGenerator shapeGenerator;

    // 存储所有实例的弱引用列表，用于批量操作（如清除缓存）
    private static final List<WeakReference<AutoVoxelShapeBlock>> instances = new ArrayList<>();

    /**
     * 构造函数
     * 
     * @param properties 方块属性
     * @param modId 模组ID
     * @param modelPath 模型文件路径
     * @param blockName 方块名称
     */
    public AutoVoxelShapeBlock(Properties properties, String modId, String modelPath, String blockName) {
        super(properties);
        this.shapeGenerator = new ModelJsonVoxelShapeParser.CachedShapeGenerator(modId, modelPath, blockName);
        this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH));
        instances.add(new WeakReference<>(this));
    }

    // ==================== 状态定义 ====================

    /**
     * 创建方块状态定义
     * 
     * @param builder 状态定义构建器
     */
    @Override
    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
        builder.add(FACING);
    }

    // ==================== 放置逻辑 ====================

    /**
     * 获取放置时的方块状态
     * 
     * @param context 放置上下文
     * @return 放置时的方块状态
     */
    @Nullable
    @Override
    public BlockState getStateForPlacement(BlockPlaceContext context) {
        return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite());
    }

    // ==================== 旋转与镜像 ====================

    /**
     * 旋转方块
     * 
     * @param state 方块状态
     * @param level 世界对象
     * @param pos 方块位置
     * @param rot 旋转方向
     * @return 旋转后的方块状态
     */
    @Override
    public @NotNull BlockState rotate(BlockState state, LevelAccessor level, BlockPos pos, Rotation rot) {
        return state.setValue(FACING, rot.rotate(state.getValue(FACING)));
    }

    /**
     * 镜像方块
     * 
     * @param state 方块状态
     * @param mirrorIn 镜像方向
     * @return 镜像后的方块状态
     */
    @Override
    @SuppressWarnings("deprecation")
    public @NotNull BlockState mirror(BlockState state, Mirror mirrorIn) {
        return state.setValue(FACING, mirrorIn.mirror(state.getValue(FACING)));
    }

    // ==================== 形状处理 ====================

    /**
     * 获取方块形状
     * 
     * @param state 方块状态
     * @param worldIn 世界对象
     * @param pos 方块位置
     * @param context 碰撞上下文
     * @return 方块形状
     */
    @Override
    @SuppressWarnings("deprecation")
    public @NotNull VoxelShape getShape(BlockState state, @NotNull BlockGetter worldIn, @NotNull BlockPos pos, @NotNull CollisionContext context) {
        Direction facing = state.getValue(FACING);
        return shapeGenerator.getShape(facing);
    }

    /**
     * 获取原始形状（不考虑朝向）
     * 
     * @return 原始形状
     */
    protected VoxelShape getBaseShape() {
        return shapeGenerator.getShape(Direction.NORTH);
    }

    /**
     * 清除当前实例的形状缓存
     */
    protected void clearShapeCache() {
        shapeGenerator.clearCache();
    }

    /**
     * 重新加载形状（清除缓存并重新生成）
     * 
     * @param direction 朝向
     * @return 重新生成的形状
     */
    protected VoxelShape reloadShape(Direction direction) {
        shapeGenerator.clearCache();
        return shapeGenerator.getShape(direction);
    }

    // ==================== 缓存管理 ====================

    /**
     * 获取方块名称
     * 
     * @return 方块名称
     */
    protected String getBlockName() {
        return shapeGenerator.getBlockName();
    }

    /**
     * 清除所有实例的缓存
     */
    public static void clearAllCaches() {
        instances.removeIf(ref -> ref.get() == null);
        for (WeakReference<AutoVoxelShapeBlock> ref : instances) {
            AutoVoxelShapeBlock block = ref.get();
            if (block != null) {
                block.clearShapeCache();
            }
        }
        // 清除全局缓存
        ModelJsonVoxelShapeParser.clearAllCache();
    }

    /**
     * 清除所有弱引用（用于垃圾回收）
     */
    public static void cleanupWeakReferences() {
        instances.removeIf(ref -> ref.get() == null);
    }

    // ==================== 粒子效果 ====================

    /**
     * 生成方块破坏时的粒子效果
     * 
     * @param level 世界对象
     * @param player 玩家对象
     * @param pos 方块位置
     * @param state 方块状态
     */
    @Override
    public void spawnDestroyParticles(Level level, @NotNull Player player, @NotNull BlockPos pos, @NotNull BlockState state) {
        // 生成粒子效果
        if (level.isClientSide) {
            // 获取方块的中心位置
            Vec3 center = pos.getCenter();
            // 生成24个粒子
            for (int i = 0; i < 24; i++) {
                level.addParticle(
                        new BlockParticleOption(ParticleTypes.BLOCK, state),
                        center.x, center.y, center.z,
                        0.0D, 0.0D, 0.0D
                );
            }
        }
    }

    /**
     * 获取方块的遮挡形状
     *
     * @param state 方块状态
     * @param level 世界对象
     * @param pos 位置
     * @return 遮挡形状
     */
    @Override
    @SuppressWarnings("deprecation")
    public @NotNull VoxelShape getOcclusionShape(@NotNull BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos) {
        // 不遮挡光线
        return Shapes.empty();
    }
}